home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / wu-ftpd-.000 / wu-ftpd- / wu-ftpd-2.4-fixed / src / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-13  |  11.4 KB  |  697 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)glob.c    5.9 (Berkeley) 2/25/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * C-shell glob for random programs.
  40.  */
  41.  
  42. #include "config.h"
  43.  
  44. #include <sys/param.h>
  45. #include <sys/stat.h>
  46.  
  47. /*#ifdef HAVE_DIRENT*/
  48. #include <dirent.h>
  49. /*#else
  50. #include <sys/dir.h>
  51. #endif
  52. */
  53.  
  54. #include <sys/stat.h>
  55. #include <pwd.h>
  56. #include <errno.h>
  57. #include <stdio.h>
  58. #include <string.h>
  59.  
  60. #define    QUOTE 0200
  61. #define    TRIM 0177
  62. #define    eq(a,b)        (strcmp(a, b)==0)
  63. #define    GAVSIZ        (NCARGS/6)
  64. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  65.  
  66. static    char **gargv;        /* Pointer to the (stack) arglist */
  67. static    int gargc;        /* Number args in gargv */
  68. static    int gnleft;
  69. static    short gflag;
  70. static    int tglob();
  71. char    **ftpglob();
  72. char    *globerr;
  73. char    *home;
  74. extern    int errno;
  75. char    *strspl();
  76. static    char *strend();
  77. char    **copyblk();
  78.  
  79. static void acollect(), addpath(), collect(), expand(), Gcat();
  80. static void ginit(), matchdir(), rscan(), sort();
  81. static int amatch(), execbrc(), match();
  82.  
  83. static    int globcnt;
  84.  
  85. char    *globchars = "`{[*?";
  86.  
  87. static    char *gpath, *gpathp, *lastgpathp;
  88. static    int globbed;
  89. static    char *entp;
  90. static    char **sortbas;
  91.  
  92. char **
  93. ftpglob(v)
  94.     register char *v;
  95. {
  96.     char agpath[BUFSIZ];
  97.     char *agargv[GAVSIZ];
  98.     char *vv[2];
  99.     vv[0] = v;
  100.     vv[1] = 0;
  101.     gflag = 0;
  102.     rscan(vv, tglob);
  103.     if (gflag == 0) {
  104.         vv[0] = strspl(v, "");
  105.         return (copyblk(vv));
  106.     }
  107.  
  108.     globerr = 0;
  109.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  110.     lastgpathp = &gpath[sizeof agpath - 2];
  111.     ginit(agargv); globcnt = 0;
  112.     collect(v);
  113.     if (globcnt == 0 && (gflag&1)) {
  114.         blkfree(gargv), gargv = 0;
  115.         return (0);
  116.     } else
  117.         return (gargv = copyblk(gargv));
  118. }
  119.  
  120. static void
  121. ginit(agargv)
  122.     char **agargv;
  123. {
  124.  
  125.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  126.     gnleft = NCARGS - 4;
  127. }
  128.  
  129. static void
  130. collect(as)
  131.     register char *as;
  132. {
  133.     if (eq(as, "{") || eq(as, "{}")) {
  134.         Gcat(as, "");
  135.         sort();
  136.     } else
  137.         acollect(as);
  138. }
  139.  
  140. static void
  141. acollect(as)
  142.     register char *as;
  143. {
  144.     register int ogargc = gargc;
  145.  
  146.     gpathp = gpath; *gpathp = 0; globbed = 0;
  147.     expand(as);
  148.     if (gargc != ogargc)
  149.         sort();
  150. }
  151.  
  152. static void
  153. sort()
  154. {
  155.     register char **p1, **p2, *c;
  156.     char **Gvp = &gargv[gargc];
  157.  
  158.     p1 = sortbas;
  159.     while (p1 < Gvp-1) {
  160.         p2 = p1;
  161.         while (++p2 < Gvp)
  162.             if (strcmp(*p1, *p2) > 0)
  163.                 c = *p1, *p1 = *p2, *p2 = c;
  164.         p1++;
  165.     }
  166.     sortbas = Gvp;
  167. }
  168.  
  169. static void
  170. expand(as)
  171.     char *as;
  172. {
  173.     register char *cs;
  174.     register char *sgpathp, *oldcs;
  175.     struct stat stb;
  176.  
  177.     sgpathp = gpathp;
  178.     cs = as;
  179.     if (*cs == '~' && gpathp == gpath) {
  180.         addpath('~');
  181.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  182.             addpath(*cs++);
  183.         if (!*cs || *cs == '/') {
  184.             if (gpathp != gpath + 1) {
  185.                 *gpathp = 0;
  186.                 if (gethdir(gpath + 1))
  187.                     globerr = "Unknown user name after ~";
  188.                 (void) strcpy(gpath, gpath + 1);
  189.             } else
  190.                 (void) strcpy(gpath, home);
  191.             gpathp = strend(gpath);
  192.         }
  193.     }
  194.     while (!any(*cs, globchars)) {
  195.         if (*cs == 0) {
  196.             if (!globbed)
  197.                 Gcat(gpath, "");
  198.             else if (stat(gpath, &stb) >= 0) {
  199.                 Gcat(gpath, "");
  200.                 globcnt++;
  201.             }
  202.             goto endit;
  203.         }
  204.         addpath(*cs++);
  205.     }
  206.     oldcs = cs;
  207.     while (cs > as && *cs != '/')
  208.         cs--, gpathp--;
  209.     if (*cs == '/')
  210.         cs++, gpathp++;
  211.     *gpathp = 0;
  212.     if (*oldcs == '{') {
  213.         (void) execbrc(cs, ((char *)0));
  214.         return;
  215.     }
  216.     matchdir(cs);
  217. endit:
  218.     gpathp = sgpathp;
  219.     *gpathp = 0;
  220. }
  221.  
  222. static void
  223. matchdir(pattern)
  224.     char *pattern;
  225. {
  226.     struct stat stb;
  227.  
  228. #ifdef HAVE_DIRENT
  229.     register struct dirent *dp;
  230. #else
  231.     register struct direct *dp;
  232. #endif
  233.  
  234.     DIR *dirp;
  235.  
  236.     dirp = opendir(*gpath == '\0' ? "." : gpath);
  237.     if (dirp == NULL) {
  238.         if (globbed)
  239.             return;
  240.         goto patherr2;
  241.     }
  242. /*    if (fstat(dirp->dd_fd, &stb) < 0)
  243.         goto patherr1;*/
  244.     if (!isdir(stb)) {
  245.         errno = ENOTDIR;
  246.         goto patherr1;
  247.     }
  248.     while ((dp = readdir(dirp)) != NULL) {
  249.         if (dp->d_ino == 0)
  250.             continue;
  251.         if (match(dp->d_name, pattern)) {
  252.             Gcat(gpath, dp->d_name);
  253.             globcnt++;
  254.         }
  255.     }
  256.     closedir(dirp);
  257.     return;
  258.  
  259. patherr1:
  260.     closedir(dirp);
  261. patherr2:
  262.     globerr = "Bad directory components";
  263. }
  264.  
  265. static int
  266. execbrc(p, s)
  267.     char *p, *s;
  268. {
  269.     char restbuf[BUFSIZ + 2];
  270.     register char *pe, *pm, *pl;
  271.     int brclev = 0;
  272.     char *lm, savec, *sgpathp;
  273.  
  274.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  275.         continue;
  276.     for (pe = ++p; *pe; pe++)
  277.     switch (*pe) {
  278.  
  279.     case '{':
  280.         brclev++;
  281.         continue;
  282.  
  283.     case '}':
  284.         if (brclev == 0)
  285.             goto pend;
  286.         brclev--;
  287.         continue;
  288.  
  289.     case '[':
  290.         for (pe++; *pe && *pe != ']'; pe++)
  291.             continue;
  292.         continue;
  293.     }
  294. pend:
  295.     brclev = 0;
  296.     for (pl = pm = p; pm <= pe; pm++)
  297.     switch (*pm & (QUOTE|TRIM)) {
  298.  
  299.     case '{':
  300.         brclev++;
  301.         continue;
  302.  
  303.     case '}':
  304.         if (brclev) {
  305.             brclev--;
  306.             continue;
  307.         }
  308.         goto doit;
  309.  
  310.     case ','|QUOTE:
  311.     case ',':
  312.         if (brclev)
  313.             continue;
  314. doit:
  315.         savec = *pm;
  316.         *pm = 0;
  317.         (void) strcpy(lm, pl);
  318.         (void) strcat(restbuf, pe + 1);
  319.         *pm = savec;
  320.         if (s == 0) {
  321.             sgpathp = gpathp;
  322.             expand(restbuf);
  323.             gpathp = sgpathp;
  324.             *gpathp = 0;
  325.         } else if (amatch(s, restbuf))
  326.             return (1);
  327.         sort();
  328.         pl = pm + 1;
  329.         if (brclev)
  330.             return (0);
  331.         continue;
  332.  
  333.     case '[':
  334.         for (pm++; *pm && *pm != ']'; pm++)
  335.             continue;
  336.         if (!*pm)
  337.             pm--;
  338.         continue;
  339.     }
  340.     if (brclev)
  341.         goto doit;
  342.     return (0);
  343. }
  344.  
  345. static int
  346. match(s, p)
  347.     char *s, *p;
  348. {
  349.     register int c;
  350.     register char *sentp;
  351.     char sglobbed = globbed;
  352.  
  353.     if (*s == '.' && *p != '.')
  354.         return (0);
  355.     sentp = entp;
  356.     entp = s;
  357.     c = amatch(s, p);
  358.     entp = sentp;
  359.     globbed = sglobbed;
  360.     return (c);
  361. }
  362.  
  363. static int
  364. amatch(s, p)
  365.     register char *s, *p;
  366. {
  367.     register int scc;
  368.     int ok, lc;
  369.     char *sgpathp;
  370.     struct stat stb;
  371.     int c, cc;
  372.  
  373.     globbed = 1;
  374.     for (;;) {
  375.         scc = *s++ & TRIM;
  376.         switch (c = *p++) {
  377.  
  378.         case '{':
  379.             return (execbrc(p - 1, s - 1));
  380.  
  381.         case '[':
  382.             ok = 0;
  383.             lc = 077777;
  384.             while (cc = *p++) {
  385.                 if (cc == ']') {
  386.                     if (ok)
  387.                         break;
  388.                     return (0);
  389.                 }
  390.                 if (cc == '-') {
  391.                     if (lc <= scc && scc <= *p++)
  392.                         ok++;
  393.                 } else
  394.                     if (scc == (lc = cc))
  395.                         ok++;
  396.             }
  397.             if (cc == 0)
  398.                 if (ok)
  399.                     p--;
  400.                 else
  401.                     return 0;
  402.             continue;
  403.  
  404.         case '*':
  405.             if (!*p)
  406.                 return (1);
  407.             if (*p == '/') {
  408.                 p++;
  409.                 goto slash;
  410.             }
  411.             s--;
  412.             do {
  413.                 if (amatch(s, p))
  414.                     return (1);
  415.             } while (*s++);
  416.             return (0);
  417.  
  418.         case 0:
  419.             return (scc == 0);
  420.  
  421.         default:
  422.             if (c != scc)
  423.                 return (0);
  424.             continue;
  425.  
  426.         case '?':
  427.             if (scc == 0)
  428.                 return (0);
  429.             continue;
  430.  
  431.         case '/':
  432.             if (scc)
  433.                 return (0);
  434. slash:
  435.             s = entp;
  436.             sgpathp = gpathp;
  437.             while (*s)
  438.                 addpath(*s++);
  439.             addpath('/');
  440.             if (stat(gpath, &stb) == 0 && isdir(stb))
  441.                 if (*p == 0) {
  442.                     Gcat(gpath, "");
  443.                     globcnt++;
  444.                 } else
  445.                     expand(p);
  446.             gpathp = sgpathp;
  447.             *gpathp = 0;
  448.             return (0);
  449.         }
  450.     }
  451. }
  452.  
  453. static
  454. Gmatch(s, p)
  455.     register char *s, *p;
  456. {
  457.     register int scc;
  458.     int ok, lc;
  459.     int c, cc;
  460.  
  461.     for (;;) {
  462.         scc = *s++ & TRIM;
  463.         switch (c = *p++) {
  464.  
  465.         case '[':
  466.             ok = 0;
  467.             lc = 077777;
  468.             while (cc = *p++) {
  469.                 if (cc == ']') {
  470.                     if (ok)
  471.                         break;
  472.                     return (0);
  473.                 }
  474.                 if (cc == '-') {
  475.                     if (lc <= scc && scc <= *p++)
  476.                         ok++;
  477.                 } else
  478.                     if (scc == (lc = cc))
  479.                         ok++;
  480.             }
  481.             if (cc == 0)
  482.                 if (ok)
  483.                     p--;
  484.                 else
  485.                     return 0;
  486.             continue;
  487.  
  488.         case '*':
  489.             if (!*p)
  490.                 return (1);
  491.             for (s--; *s; s++)
  492.                 if (Gmatch(s, p))
  493.                     return (1);
  494.             return (0);
  495.  
  496.         case 0:
  497.             return (scc == 0);
  498.  
  499.         default:
  500.             if ((c & TRIM) != scc)
  501.                 return (0);
  502.             continue;
  503.  
  504.         case '?':
  505.             if (scc == 0)
  506.                 return (0);
  507.             continue;
  508.  
  509.         }
  510.     }
  511. }
  512.  
  513. static void
  514. Gcat(s1, s2)
  515.     register char *s1, *s2;
  516. {
  517.     register int len = strlen(s1) + strlen(s2) + 1;
  518.  
  519.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  520.         globerr = "Arguments too long";
  521.     else {
  522.         gargc++;
  523.         gnleft -= len;
  524.         gargv[gargc] = 0;
  525.         gargv[gargc - 1] = strspl(s1, s2);
  526.     }
  527. }
  528.  
  529. static void
  530. addpath(c)
  531.     char c;
  532. {
  533.  
  534.     if (gpathp >= lastgpathp)
  535.         globerr = "Pathname too long";
  536.     else {
  537.         *gpathp++ = c;
  538.         *gpathp = 0;
  539.     }
  540. }
  541.  
  542. static void
  543. rscan(t, f)
  544.     register char **t;
  545.     int (*f)();
  546. {
  547.     register char *p, c;
  548.  
  549.     while (p = *t++) {
  550.         if (f == tglob)
  551.             if (*p == '~')
  552.                 gflag |= 2;
  553.             else if (eq(p, "{") || eq(p, "{}"))
  554.                 continue;
  555.         while (c = *p++)
  556.             (*f)(c);
  557.     }
  558. }
  559. /*
  560. static
  561. scan(t, f)
  562.     register char **t;
  563.     int (*f)();
  564. {
  565.     register char *p, c;
  566.  
  567.     while (p = *t++)
  568.         while (c = *p)
  569.             *p++ = (*f)(c);
  570. } */
  571.  
  572. static
  573. tglob(c)
  574.     register char c;
  575. {
  576.  
  577.     if (any(c, globchars))
  578.         gflag |= c == '{' ? 2 : 1;
  579.     return (c);
  580. }
  581. /*
  582. static
  583. trim(c)
  584.     char c;
  585. {
  586.  
  587.     return (c & TRIM);
  588. } */
  589.  
  590.  
  591. letter(c)
  592.     register char c;
  593. {
  594.  
  595.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  596. }
  597.  
  598. digit(c)
  599.     register char c;
  600. {
  601.  
  602.     return (c >= '0' && c <= '9');
  603. }
  604.  
  605. any(c, s)
  606.     register int c;
  607.     register char *s;
  608. {
  609.  
  610.     while (*s)
  611.         if (*s++ == c)
  612.             return(1);
  613.     return(0);
  614. }
  615. blklen(av)
  616.     register char **av;
  617. {
  618.     register int i = 0;
  619.  
  620.     while (*av++)
  621.         i++;
  622.     return (i);
  623. }
  624.  
  625. char **
  626. blkcpy(oav, bv)
  627.     char **oav;
  628.     register char **bv;
  629. {
  630.     register char **av = oav;
  631.  
  632.     while (*av++ = *bv++)
  633.         continue;
  634.     return (oav);
  635. }
  636.  
  637. blkfree(av0)
  638.     char **av0;
  639. {
  640.     register char **av = av0;
  641.  
  642.     while (*av)
  643.         free(*av++);
  644. }
  645.  
  646. char *
  647. strspl(cp, dp)
  648.     register char *cp, *dp;
  649. {
  650.     register char *ep = (char *) malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  651.  
  652.     if (ep == (char *)0)
  653.         fatal("Out of memory");
  654.     (void) strcpy(ep, cp);
  655.     (void) strcat(ep, dp);
  656.     return (ep);
  657. }
  658.  
  659. char **
  660. copyblk(v)
  661.     register char **v;
  662. {
  663.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  664.                         sizeof(char **)));
  665.     if (nv == (char **)0)
  666.         fatal("Out of memory");
  667.  
  668.     return (blkcpy(nv, v));
  669. }
  670.  
  671. static
  672. char *
  673. strend(cp)
  674.     register char *cp;
  675. {
  676.  
  677.     while (*cp)
  678.         cp++;
  679.     return (cp);
  680. }
  681. /*
  682.  * Extract a home directory from the password file
  683.  * The argument points to a buffer where the name of the
  684.  * user whose home directory is sought is currently.
  685.  * We write the home directory of the user back there.
  686.  */
  687. gethdir(home)
  688.     char *home;
  689. {
  690.     register struct passwd *pp = getpwnam(home);
  691.  
  692.     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
  693.         return (1);
  694.     (void) strcpy(home, pp->pw_dir);
  695.     return (0);
  696. }
  697.